//
// Created by pengmutian on 2025/9/30.
//
#include <jni.h>
#include <mutex>
#include "JNIEnvAutoRelease.h"

class ThreadSafeJNI {
private:
    JavaVM* javaVM_;
    std::mutex callbackMutex_;
    jobject globalCallback_;

public:
    ThreadSafeJNI(JavaVM* jvm) : javaVM_(jvm), globalCallback_(nullptr) {}

    bool setCallback(JNIEnv* env, jobject callback) {
        std::lock_guard<std::mutex> lock(callbackMutex_);

        if (globalCallback_ != nullptr) {
            env->DeleteGlobalRef(globalCallback_);
        }

        if (callback != nullptr) {
            globalCallback_ = env->NewGlobalRef(callback);
            return globalCallback_ != nullptr;
        } else {
            globalCallback_ = nullptr;
            return true;
        }
    }

    void safeCallback(int eventType, const std::string& message) {
        std::lock_guard<std::mutex> lock(callbackMutex_);

        if (globalCallback_ == nullptr) {
            return;
        }

        JNIEnvAutoRelease env(javaVM_);
        jclass callbackClass = env->GetObjectClass(globalCallback_);
        jmethodID methodId = env->GetMethodID(callbackClass, "onNativeEvent",
                                              "(ILjava/lang/String;)V");

        if (methodId != nullptr) {
            jstring jMessage = env->NewStringUTF(message.c_str());
            env->CallVoidMethod(globalCallback_, methodId, eventType, jMessage);
            env->DeleteLocalRef(jMessage);
        }

        env->DeleteLocalRef(callbackClass);
    }
};
